package thread;
//为了简单,不考虑使用泛型的元素,此处单纯使用String
class MyBlockingQueue{
    private String[] elems = null;
    private int head = 0;
    private int tail = 0;
    private int size = 0;
    private Object locker = new Object();
    public MyBlockingQueue(int capacity){
        elems = new String[capacity];
    }
    public void put(String elem) throws InterruptedException {
        synchronized (locker){
            while (size>=elems.length){
                //队列满了
                //后续需要这个代码能够实现阻塞
                locker.wait(); 
            }
            //新的元素要放到tail指向的位置上
            elems[tail] = elem;
            tail++;
            if(tail>= elems.length){
                tail = 0;
            }
            //可以写成tail = tail % elems.length;但除法运算效率比条件跳转要低
            size++;
            //入队列成功后唤醒
            locker.notify();

        }
    }
    public String take() throws InterruptedException {
        synchronized (locker){
            while (size == 0){
                //队列空了,后续也需要让这个代码阻塞
                locker.wait();
            }
            //如果队列不为空,我们需要取出head位置的元素并返回
            String elem = elems[head];
            head++;
            if(head>= elems.length){
                head = 0;
            }
            size--;
            //出队列后唤醒
            locker.notify();
            return elem;
        }
    }


}
public class ThreadDemo4 {
    public static void main(String[] args) throws InterruptedException {
        MyBlockingQueue mbq = new MyBlockingQueue(1000);
        //mbq.put("aaa");
        //mbq.put("bbb");
        //mbq.put("ccc");
        //mbq.put("ddd");
        //String elem = mbq.take();
        //System.out.println(elem);
        //elem = mbq.take();
        //System.out.println(elem);
        //elem = mbq.take();
        //System.out.println(elem);
        //elem = mbq.take();
        //System.out.println(elem);
        Thread t1 = new Thread(()->{
            int n = 1;
            while (true){
                try {
                    mbq.put(n+"");
                    System.out.println("生产元素" + n);
                    n++;
                    //此处加上sleep,生产者生产慢,消费者消费得快
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }

            }
        });
        Thread t2 = new Thread(()->{
            while (true){
                try {
                    String n = mbq.take();
                    System.out.println("消费者元素"+n);
                    Thread.sleep(500);//此处加上sleep,说明生产者生产的快,消费者消费的慢
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }

            }
        });
        t1.start();
        t2.start();

    }
}
